package com.ceair.controller;

import com.ceair.config.MyUrlConfig;
import com.ceair.entity.model.Result;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.util.UrlUtils;
import org.springframework.stereotype.Controller;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.util.UriComponentsBuilder;
import org.springframework.web.util.UriUtils;

import java.nio.charset.StandardCharsets;

/**
 * @author wangbaohai
 * @ClassName AuthorizationController
 * @description: 认证服务器相关自定接口
 * @date 2024年11月15日
 * @version: 1.0.0
 */
@Controller
@RequiredArgsConstructor
public class AuthorizationController {

    private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

    /**
     * 处理OAuth2授权同意页面的重定向请求。
     * 该函数根据请求参数构建重定向URL，并根据是否为设备码模式决定是直接重定向还是返回JSON响应。
     *
     * @param session 当前HTTP会话，用于存储会话相关的信息。
     * @param request HTTP请求对象，包含客户端请求的所有信息。
     * @param response HTTP响应对象，用于向客户端发送响应。
     * @param scope OAuth2授权请求中的scope参数，表示请求的权限范围。
     * @param state OAuth2授权请求中的state参数，用于防止CSRF攻击。
     * @param clientId OAuth2授权请求中的client_id参数，表示客户端的唯一标识。
     * @param userCode OAuth2设备码授权模式中的user_code参数，表示用户设备码（可选）。
     * @return 如果请求为设备码模式且需要前端跳转，则返回包含重定向URL的Result对象；否则返回null，直接进行重定向。
     */
    @SneakyThrows
    @ResponseBody
    @GetMapping(value = "/oauth2/consent/redirect")
    public Result<String> consentRedirect(HttpSession session,
                                          HttpServletRequest request,
                                          HttpServletResponse response,
                                          @RequestParam(OAuth2ParameterNames.SCOPE) String scope,
                                          @RequestParam(OAuth2ParameterNames.STATE) String state,
                                          @RequestParam(OAuth2ParameterNames.CLIENT_ID) String clientId,
                                          @RequestParam(name = OAuth2ParameterNames.USER_CODE, required = false) String userCode) {

        // 构建重定向URL，包含scope、state、clientId和userCode等参数
        UriComponentsBuilder uriBuilder = UriComponentsBuilder
                .fromUriString(MyUrlConfig.CONSENT_PAGE_URI)
                .queryParam(OAuth2ParameterNames.SCOPE, UriUtils.encode(scope, StandardCharsets.UTF_8))
                .queryParam(OAuth2ParameterNames.STATE, UriUtils.encode(state, StandardCharsets.UTF_8))
                .queryParam(OAuth2ParameterNames.CLIENT_ID, clientId)
                .queryParam(OAuth2ParameterNames.USER_CODE, userCode);

        String uriString = uriBuilder.build(Boolean.TRUE).toUriString();

        // 判断是否为设备码模式且设备码验证页面是否为前后端分离
        if (ObjectUtils.isEmpty(userCode) || !UrlUtils.isAbsoluteUrl(MyUrlConfig.DEVICE_ACTIVATE_URI)) {
            // 如果不是设备码模式或设备码验证页面不是前后端分离的，直接重定向
            this.redirectStrategy.sendRedirect(request, response, uriString);
            return null;
        }

        // 如果是设备码模式且需要前端跳转，返回包含重定向URL的JSON响应
        return Result.success(uriString);
    }
}
